package com.billdowney.util.network;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import org.apache.http.Consts;
import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.ParseException;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;

import com.billdowney.util.CommonUtil;

import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;

/**
 * @ClassName: HttpSendUtil
 * @Description: http请求工具包
 * @author 超级小富翁 - BillDowney
 * @date 2018年1月10日 上午11:31:38
 */
public class HttpSendUtil {

	// utf-8字符编码
	public static final String CHARSET_CHARSET = "utf-8";

	// HTTP内容类型。
	public static final String CONTENT_TYPE_TEXT_HTML = "text/xml";

	// HTTP内容类型。相当于form表单的形式，提交数据
	public static final String CONTENT_TYPE_FORM_URL = "application/x-www-form-urlencoded";

	// HTTP内容类型。相当于json格式的形式，提交数据
	public static final String CONTENT_TYPE_JSON_URL = "application/json;charset=utf-8";

	// 超时时间， 默认20*1000毫秒
	public static final int TIME_OUT = 20000;

	/**
	 * @Function: doGetByJSON
	 * @Description: 发送get请求，得到一个JSON数据对象
	 * @param url 请求url地址
	 * @return JSON格式数据
	 * @author: 超级小富翁 - BillDowney
	 * @date: 2018年1月10日 下午4:22:44
	 */
	public JSONObject doGetByJSON(String url) {
		try {
			return JSONUtil.parseObj(doGetSend(url, null, null));
		} catch (Exception e) {
			e.printStackTrace();
			return new JSONObject();
		}
	}

	/**
	 * @Description: 发送get请求，得到一个JSON数据对象
	 * @param url    请求url地址
	 * @param params 参数
	 * @return
	 * @author: 唐路钧
	 * @date: 2018年11月8日 上午10:23:52
	 */
	public JSONObject doGetByJSON(String url, Map<String, Object> params) {
		try {
			return JSONUtil.parseObj(doGetSend(url, params, null));
		} catch (Exception e) {
			e.printStackTrace();
			return new JSONObject();
		}
	}

	/**
	 * @Description: 发送get请求，得到一个JSON数据对象
	 * @param url     请求url地址
	 * @param headers 请求头
	 * @return JSON格式数据
	 * @author: 超级小富翁 - BillDowney
	 * @date: 2018年1月10日 下午3:21:53
	 */
	public JSONObject doGetAndHeadersByJSON(String url, Map<String, Object> headers) {
		try {
			return JSONUtil.parseObj(doGetSend(url, null, headers));
		} catch (Exception e) {
			e.printStackTrace();
			return new JSONObject();
		}
	}

	/**
	 * @Function: doGetByJSON
	 * @Description: 发送get请求，得到一个JSON数据对象
	 * @param url     请求url地址
	 * @param params  请求参数
	 * @param headers 请求头
	 * @return JSON格式数据
	 * @author: 超级小富翁 - BillDowney
	 * @date: 2018年1月10日 下午3:22:15
	 */
	public JSONObject doGetByJSON(String url, Map<String, Object> params, Map<String, Object> headers) {
		try {
			return JSONUtil.parseObj(doGetSend(url, params, headers));
		} catch (Exception e) {
			e.printStackTrace();
			return new JSONObject();
		}
	}

	/**
	 * @Function: doGetByString
	 * @Description: 发送get请求，得到一个String数据对象
	 * @param url 请求url地址
	 * @return String格式数据
	 * @author: 超级小富翁 - BillDowney
	 * @date: 2018年5月17日 上午10:00:07
	 */
	public String doGetByString(String url) {
		return doGetSend(url, null, null);
	}

	/**
	 * @Description: 发送get请求，得到一个String数据对象
	 * @param url    请求url地址
	 * @param params 参数
	 * @return String格式数据
	 * @author: 唐路钧
	 * @date: 2018年11月8日 上午10:27:05
	 */
	public String doGetByString(String url, Map<String, Object> params) {
		return doGetSend(url, params, null);
	}

	/**
	 * @Function: doGetByString
	 * @Description: 发送get请求，得到一个String数据对象
	 * @param url     请求url地址
	 * @param headers 请求头
	 * @return String格式数据
	 * @author: 超级小富翁 - BillDowney
	 * @date: 2018年5月17日 上午10:00:11
	 */
	public String doGetAndHeadersByString(String url, Map<String, Object> headers) {
		return doGetSend(url, null, headers);
	}

	/**
	 * @Function: doGetByString
	 * @Description: 发送get请求，得到一个String数据对象
	 * @param url     请求url地址
	 * @param params  请求参数
	 * @param headers 请求头
	 * @return String格式数据
	 * @author: 超级小富翁 - BillDowney
	 * @date: 2018年5月17日 上午10:00:14
	 */
	public String doGetByString(String url, Map<String, Object> params, Map<String, Object> headers) {
		return doGetSend(url, params, headers);
	}

	/**
	 * @Function: doGetSend
	 * @Description: 发送get请求，得到一个String数据对象
	 * @param url     请求url地址
	 * @param params  请求参数
	 * @param headers 请求头
	 * @return 得到请求的字符串
	 * @author: 超级小富翁 - BillDowney
	 * @date: 2018年1月10日 下午2:46:53
	 */
	private String doGetSend(String url, Map<String, Object> params, Map<String, Object> headers) {
		String out = "";
		// 1. 创建一个默认的client实例
		CloseableHttpClient client = HttpClients.createDefault();
		if (CommonUtil.isNotEmpty(params)) {
			List<NameValuePair> formparams = new ArrayList<NameValuePair>();
			for (Entry<String, Object> entry : params.entrySet()) {
				// 给参数赋值
				formparams.add(new BasicNameValuePair(entry.getKey(), entry.getValue().toString()));
			}
			if (params.size() > 0) {
				try {
					url += "?" + EntityUtils.toString(new UrlEncodedFormEntity(formparams, Consts.UTF_8));
				} catch (ParseException | IOException e) {
					e.printStackTrace();
				}
			}
		}
		try {
			// 2. 创建一个httpget对象
			HttpGet httpGet = new HttpGet(url);
			if (CommonUtil.isNotEmpty(headers)) {
				Set<String> keys = headers.keySet();
				for (String key : keys) {
					httpGet.setHeader(key, headers.get(key).toString());
				}
			}
			// 3. 设置超时时间
			RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(TIME_OUT).setConnectTimeout(TIME_OUT)
					.build();
			httpGet.setConfig(requestConfig);
			// 4. 执行GET请求并获取响应对象
			CloseableHttpResponse resp = client.execute(httpGet);
			try {
				// 5. 返回响应体
				HttpEntity entity = resp.getEntity();
				if (CommonUtil.isNotEmpty(entity)) {
					out = EntityUtils.toString(entity);
				}
			} finally {
				// 6. 无论请求成功与否都要关闭resp
				resp.close();
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			// 7. 最终要关闭连接，释放资源
			try {
				client.close();
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		return out;
	}

	/**
	 * @Function: doPostByJSON
	 * @Description: 发送post请求，得到一个JSON数据对象
	 * @param url 请求url地址
	 * @return JSON格式数据
	 * @author: 超级小富翁 - BillDowney
	 * @date: 2018年1月10日 下午4:23:31
	 */
	public JSONObject doPostByJSON(String url) {
		try {
			return JSONUtil.parseObj(doGetSend(url, null, null));
		} catch (Exception e) {
			e.printStackTrace();
			return new JSONObject();
		}
	}

	/**
	 * @Function: doPostByJSON
	 * @Description: 发送post请求，得到一个JSON数据对象
	 * @param url    请求url地址
	 * @param params 请求参数
	 * @return JSON格式数据
	 * @author: 超级小富翁 - BillDowney
	 * @date: 2018年1月10日 下午3:25:26
	 */
	public JSONObject doPostByJSON(String url, Map<String, Object> params) {
		try {
			return JSONUtil.parseObj(doPostSend(url, params, null));
		} catch (Exception e) {
			e.printStackTrace();
			return new JSONObject();
		}
	}

	/**
	 * @Description: 发送post请求，得到一个JSON数据对象
	 * @param url     请求url地址
	 * @param headers 发送的头部
	 * @return
	 * @author: 唐路钧
	 * @date: 2018年11月8日 上午10:22:27
	 */
	public JSONObject doPostAndHeadersByJSON(String url, Map<String, Object> headers) {
		try {
			return JSONUtil.parseObj(doPostSend(url, null, headers));
		} catch (Exception e) {
			e.printStackTrace();
			return new JSONObject();
		}
	}

	/**
	 * @Function: doPostByJSON
	 * @Description: 发送post请求，得到一个JSON数据对象
	 * @param url     请求url地址
	 * @param params  请求参数
	 * @param headers 请求头
	 * @return JSON格式数据
	 * @author: 超级小富翁 - BillDowney
	 * @date: 2018年1月10日 下午3:26:28
	 */
	public JSONObject doPostByJSON(String url, Map<String, Object> params, Map<String, Object> headers) {
		try {
			return JSONUtil.parseObj(doPostSend(url, params, headers));
		} catch (Exception e) {
			e.printStackTrace();
			return new JSONObject();
		}
	}

	/**
	 * @Function: doPostByString
	 * @Description: 发送post请求，得到一个String数据对象
	 * @param url 请求url地址
	 * @return String格式数据
	 * @author: 超级小富翁 - BillDowney
	 * @date: 2018年5月17日 上午10:04:44
	 */
	public String doPostByString(String url) {
		return doPostSend(url, null, null);
	}

	/**
	 * @Description: 发送post请求，得到一个String数据对象
	 * @param url    请求url地址
	 * @param params 参数
	 * @return String格式数据
	 * @author: 唐路钧
	 * @date: 2018年11月8日 上午10:26:23
	 */
	public String doPostByString(String url, Map<String, Object> params) {
		return doPostSend(url, params, null);
	}

	/**
	 * @Function: doPostByString
	 * @Description: 发送post请求，得到一个String数据对象
	 * @param url     请求url地址
	 * @param headers 请求头
	 * @return String格式数据
	 * @author: 超级小富翁 - BillDowney
	 * @date: 2018年5月17日 上午10:04:47
	 */
	public String doPostAndHeadersByString(String url, Map<String, Object> headers) {
		return doPostSend(url, null, headers);
	}

	/**
	 * @Function: doPostByString
	 * @Description: 发送post请求，得到一个String数据对象
	 * @param url     请求url地址
	 * @param params  请求参数
	 * @param headers 请求头
	 * @return String格式数据
	 * @author: 超级小富翁 - BillDowney
	 * @date: 2018年5月17日 上午10:04:54
	 */
	public String doPostByString(String url, Map<String, Object> params, Map<String, Object> headers) {
		return doPostSend(url, params, headers);
	}

	/**
	 * @Function: doPostSend
	 * @Description: 发送post请求，得到一个String数据对象
	 * @param url     请求url地址
	 * @param params  请求参数
	 * @param headers 请求头
	 * @return 得到请求的字符串
	 * @author: 超级小富翁 - BillDowney
	 * @date: 2018年1月10日 下午3:27:46
	 */
	private String doPostSend(String url, Map<String, Object> params, Map<String, Object> headers) {
		String out = "";
		// 1. 创建一个默认的client实例
		CloseableHttpClient client = HttpClients.createDefault();
		List<NameValuePair> formparams = new ArrayList<NameValuePair>();
		if (CommonUtil.isNotEmpty(params)) {
			for (Entry<String, Object> entry : params.entrySet()) {
				// 给参数赋值
				formparams.add(new BasicNameValuePair(entry.getKey(), entry.getValue().toString()));
			}
			if (params.size() > 0) {
				try {
					url += "?" + EntityUtils.toString(new UrlEncodedFormEntity(formparams, Consts.UTF_8));
				} catch (ParseException | IOException e) {
					e.printStackTrace();
				}
			}
		}
		try {
			// 2. 创建一个HttpPost对象
			HttpPost httpPost = new HttpPost(url);
			if (CommonUtil.isNotEmpty(headers)) {
				Set<String> keys = headers.keySet();
				for (String key : keys) {
					httpPost.setHeader(key, headers.get(key).toString());
				}
			}
			httpPost.setEntity(new UrlEncodedFormEntity(formparams, "UTF-8"));
			// 3. 设置超时时间
			RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(TIME_OUT).setConnectTimeout(TIME_OUT)
					.build();
			httpPost.setConfig(requestConfig);
			// 4. 执行GET请求并获取响应对象
			CloseableHttpResponse resp = client.execute(httpPost);
			try {
				// 5. 返回响应体
				HttpEntity entity = resp.getEntity();
				if (CommonUtil.isNotEmpty(entity)) {
					out = EntityUtils.toString(entity);
				}
			} finally {
				// 6. 无论请求成功与否都要关闭resp
				resp.close();
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			// 7. 最终要关闭连接，释放资源
			try {
				client.close();
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		return out;
	}

}
